/*================================================================
*   Copyright (C) 2022 Sangfor Ltd. All rights reserved.
*   
*   文件名称：oj_model.hpp
*   创 建 者：wudu
*   创建日期：2022年03月30日
*   描    述：处理试题信息
*               1.加载试题信息
*               2.提供接口可以让http模块进行调用
*
*             N多个试题， 在后台代码当中如何管理？
*                管理 = 描述（结构体） + 组织（数据结构）
*             
*             代码实现思路：
*               1. 描述单个试题信息
*               2. 能够将多个试题信息组织起来（数据结构）
================================================================*/
#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#include <fstream>

#include "tools.hpp"

using namespace std;

//描述单个试题
struct Question{
    //题目的id
    string id_;
    //题目的名称
    string title_;
    //题目的难易程度
    string star_;
    //题目具体信息在磁盘当中的位置
    string path_;

    //题目描述
    string desc_;
    //题目的预定义头
    string header_cpp_;
    //题目预定义的尾
    string tail_cpp_;
};



class OjModel{
    public:
        OjModel(){
            bool ret = Load("./oj_data/oj_config.cfg");
            if(ret == false){
                printf("Load file falied\n");
                exit(1);
            }
        }

        ~OjModel(){

        }
        /*
         * 提供给http模块进行调用，以获取全部试题信息
         * */
        bool GetAllQuetion(vector<Question>& vec){
           //1.遍历map， 获取试题信息， 并且放到vec当中
            for(const auto& kv : ques_map_){
                vec.push_back(kv.second);
            }

           //2.针对vec进行排序， 按照题目id进行升序
            sort(vec.begin(), vec.end(), [](const Question& l, const Question& r){
                        return stoi(l.id_) < stoi(r.id_);
                    });
            return true;
        }

        /*
         * 提供给http模块进行调用， 以获取单个试题的信息
         * id : 调用者提供想要获取试题的ID
         * ques ： 返回给调用者的试题信息
         * */
        bool GetOneQuestion(const string& id, Question* ques){
            auto iter = ques_map_.find(id);
            if(iter == ques_map_.end()){
                return false;
            }
            *ques = iter->second;
            return true;
        }
    private:
        /*
         * 从磁盘当中读取试题内容
         * */
        bool Load(const string& filename){
            //1.C- fopen, fwrite, fseek, fclose, fread
            //2.系统编程 open/read/write/lseek/close
            //3.C++: 文件流 ifstream
            //
            
            //1.打开试题配置文件
            ifstream file(filename.c_str());
            if(!file.is_open()){
                return false;
            }

            //如果代码能够走到这边， 那说明， 我们打开文件成功了
            //2.读文件
            string line;
            while(getline(file, line)){
                //id 题目名称 题目的难易程度 题目的路径
                /*
                 * boost::split(
                 *    将切割后的字符串存放在哪里
                 *    要切分的内容
                 *    要按照什么字符来进行切分
                 *    是否要将多个同样的切割字符进行压缩处理
                 * )
                 * */

                vector<string> vec;
                string split_char = " ";
                StringUtil::Spilt(line, split_char, &vec);

                Question ques;
                ques.id_ = vec[0];
                ques.title_ = vec[1];
                ques.star_ = vec[2];
                ques.path_ = vec[3];

                //将desc， header.cpp, tail.cpp的内容读回来
                //./oj_data/1/desc.txt
                FileUtil::ReadFile(ques.path_+"/desc.txt", &ques.desc_);
                FileUtil::ReadFile(ques.path_+"/header.cpp", &ques.header_cpp_);
                FileUtil::ReadFile(ques.path_+"/tail.cpp", &ques.tail_cpp_);

                ques_map_[ques.id_] = ques;
            }
            file.close();
            return true;
        }
    private:
        //string : 题目id
        //Question ： 题目的具体信息
        unordered_map<string, Question> ques_map_;
};
















